package com.netty.modbus.dto.response;

import com.netty.modbus.exception.DataConvertException;
import com.netty.modbus.util.CRC16;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

/**
 * description: RequestBody <br>
 * date: 2021/9/29 9:03 <br>
 * @author: lwy <br>
 * @version: 1.0 <br>
 */
public abstract class ResponseBody {

    private byte command;

    private byte[] start;

    private byte[] end;

    private byte[] dataContent;

    private byte[] verifyContent;

    private byte[] verifyCode;


    /**
     * description: 解码
     * version: 1.0
     * date: 2021/9/29 9:41
     * @author: lwy
     * @param data
     * @return void
     */
    public abstract void decode(byte[] data);

    /**
     * description: 公用的解码
     * version: 1.0
     * date: 2021/9/29 15:52
     * @author: lwy
     * @param length 字节长度
     * @param data 报文完整内容
     * @return void
     */
    public void commDecode(int length,byte[] data){
        byte[] start=new byte[2];
        System.arraycopy(data, 0, start, 0, 2);
        setStart(start);

        byte[] end=new byte[2];
        System.arraycopy(data, length-2, end, 0, 2);
        setEnd(end);

        //校验内容长度=总长度-前缀（2）-后缀（2）-校验（2）
        int verifyLength = length - 6;
        byte[] verifyContent = new byte[verifyLength];
        System.arraycopy(data, 2, verifyContent, 0, verifyLength);
        setVerifyContent(verifyContent);

        //校验码
        byte[] verifyCode = new byte[2];
        System.arraycopy(data, length - 4, verifyCode, 0, 2);
        setVerifyCode(verifyCode);

        //数据内容长度=总长度-前缀（2）-命令字（1）-后缀（2）-校验（2）
        int dataLength=length-7;
        byte[] dataContent=new byte[dataLength];
        System.arraycopy(data, 3, dataContent, 0, dataLength);
        setDataContent(dataContent);

        setCommand(data[2]);

    }

    /**
     * description: 公用编码
     * version: 1.0
     * date: 2021/9/29 16:02
     * @author: lwy
     * @param data 要返回的数据内容
     * @return void
     */
    public ByteBuf commEncode(byte[] data){
        ByteBuf buf = Unpooled.buffer();
        //起始符
        buf.writeBytes(this.getStart());
        //命令字
        buf.writeByte(this.getCommand());
        if(data!=null){
            //有返回数据
            //数据内容
            buf.writeBytes(data);
            byte[] verifyContent=new byte[1+data.length];
            verifyContent[0]=this.getCommand();
            System.arraycopy(data,0,verifyContent,1,data.length);
            //校验码
            buf.writeBytes(CRC16.crc16(verifyContent)) ;
        }else{
            byte[] verifyContent=new byte[1];
            verifyContent[0]=this.getCommand();
            //校验码
            buf.writeBytes(CRC16.crc16(verifyContent));
        }
        buf.writeBytes(this.getEnd());
        return buf;
    }

    /**
     * description: encode
     * version: 1.0
     * @date: 2021/9/29 11:11
     * @author: lwy
     * @param
     * @return io.netty.buffer.ByteBuf
     */
    public abstract ByteBuf  encode() throws DataConvertException;


    public byte getCommand() {
        return command;
    }

    public void setCommand(byte command) {
        this.command = command;
    }

    public byte[] getEnd() {
        return end;
    }

    public void setEnd(byte[] end) {
        this.end = end;
    }

    public byte[] getDataContent() {
        return dataContent;
    }

    public void setDataContent(byte[] dataContent) {
        this.dataContent = dataContent;
    }

    public byte[] getStart() {
        return start;
    }

    public void setStart(byte[] start) {
        this.start = start;
    }

    public byte[] getVerifyContent() {
        return verifyContent;
    }

    public void setVerifyContent(byte[] verifyContent) {
        this.verifyContent = verifyContent;
    }

    public byte[] getVerifyCode() {
        return verifyCode;
    }

    public void setVerifyCode(byte[] verifyCode) {
        this.verifyCode = verifyCode;
    }
}
